package com.xwx.common.controller;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.TableMapping;
import com.jfinal.token.TokenManager;
import com.xwx.common.model.ModelExt;
import com.xwx.common.utils.Condition;
/**
 * @Description:通用Controller 所有继承此类的子级都必须是继承baseModel,提供基础CRUD操作
 * @author:Dream QQ:68697015
 * @time:2015年8月14日 上午11:15:36
 */
public class GeneralController<M extends ModelExt<M>> extends BaseController {
	//当前model
	protected Class<M> modelClass;
	//当前主键名
	protected String primaryKey;
	/**
	 * 初始化,根据当前class反射model信息
	 */
	@SuppressWarnings("unchecked")
	public GeneralController() {
		  Type t = getClass().getGenericSuperclass();  
		  Type[] params = ((ParameterizedType) t).getActualTypeArguments(); 
		  modelClass=(Class<M>) params[0];
		  //主键
		  primaryKey=TableMapping.me().getTable(modelClass).getPrimaryKey()[0];
	}
	/**
	 * 默认首页
	 */
	public void index()throws Exception{
		render(PropKit.get("index"));
	}
	/**
	 * 通用request获取当前对象model
	 * 在表单中可直接使用名称而不需要加类名
	 * RequestAutoModel
	 * @return Model
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public Model getRAM() throws Exception {
		HttpServletRequest request = this.getRequest();
		Model model_ = (Model) getNewInstance();
		model_.getAttrNames();
		Enumeration<String> attrNames = request.getParameterNames();
		while(attrNames.hasMoreElements()) {
			String key = attrNames.nextElement();
			String value=request.getParameter(key);
			//检测是否存在该字段
			if(TableMapping.me().getTable(modelClass).hasColumnLabel(key)){
				model_.set(key, value);
			}else{
				model_.put(key, value);
			}
		}
		log.info("页面参数取值成功："+model_.toJson());
		return model_;
	}
	/**
	 * 默认编辑页
	 * 可接收主键参数,如http://xxx.com/23
	 * 如果没有传入主键则新增，model为null
	 * 如果有主键，则编辑 model有内容
	 */
	public void edit()throws Exception{
		String id=getPara();//接收id
		M _model = null;
		if(StrKit.notBlank(id) && !id.equals("0")){
			_model=queryById(id);
			log.info("编辑数据");
		}else{
			log.info("新增数据");
		}
		setAttr("model", _model);
		if(isToKen)createToken(TOKEN_KEY, tokenTime);
		render(PropKit.get("edit"));
	}	
	/**
	 * 通用保存
	 */
	@SuppressWarnings("unchecked")
	public void save() throws Exception{
		if(isToKen){
			boolean tk=TokenManager.validateToken(this, TOKEN_KEY);
			if(!tk) throw new Exception("请勿重复提交表单，会产生错误数据");
		}
		Model<M> _model=this.getRAM();
		if(TableMapping.me().getTable(modelClass).hasColumnLabel("createUserId"))_model.set("createUserId", getSeesionUserId());
		_model.save();
		log.info("save success");
		renderJson();
	}
	/**
	 * 通用更新
	 * 主键从request中获取
	 * 提交地址为 http://www.gbdc.com/update/20,其中20为更新的主键编号
	 * 返回JSON数据
	 */
	@SuppressWarnings("unchecked")
	public void update() throws Exception{
		Model<M> _model=this.getRAM();
		//检测是否有主键
		if(StrKit.isBlank(getPara())){
			//无参数主键
			if(StrKit.isBlank(getPara(primaryKey))){
				//没主键
				throw new NullPointerException("没有主键，无法更新");
			}else{
				_model.set(primaryKey, this.getPara());
			}
		}else{
			_model.set(primaryKey, this.getPara());
		}
		//增加修改用户，如果有
		if(TableMapping.me().getTable(modelClass).hasColumnLabel("updateUserId"))_model.set("updateUserId", getSeesionUserId());
		_model.update();
		log.info("update success");
		renderJson();		
	}
	/**
	 * 通用删除
	 * @throws Exception
	 */
	public void del()throws Exception{
		String id=getPara();
		if(StrKit.isBlank(id))throw new NullPointerException("参数无效");
		getNewInstance().deleteById(getPara());
		log.info("del success");
		renderJson();		
	}
	/**
	 * 批量删除
	 * 需要传递ids的参数，如ids="1,2,3,4";
	 * @throws Exception
	 */
	public void batchDel()throws Exception{
		String ids=this.getPara("ids");
		if(StrKit.isBlank(ids))throw new NullPointerException("参数无效");
		getNewInstance().deleteByCondition(new Condition().in(ids, primaryKey).toString());
		log.info("batchDel success");
		renderJson();
	}
	/**
	 * 启用状态 值为0
	 * 需传入id
	 */
	public void enable()throws Exception{
		getNewInstance().enable();
		log.info("enable success");
		renderJson();
	}
	/**
	 * 禁用状态 设为1
	 * 需传入ID
	 * @throws Exception
	 */
	public void disable()throws Exception{
		getNewInstance().disable();
		log.info("disable success");
		renderJson();		
	} 
	/**
	 * 根据主键查询
	 * @param obj
	 * @return
	 */
	public M queryById(Object obj)throws Exception{
		if(StrKit.isBlank(obj.toString()))throw new NullPointerException("参数无效");
		return getNewInstance().queryById(obj);
	}
	/**
	 * 检测是否有存在子级数据
	 * @param id 要检测的节点ID
	 * @return true 存在
	 */
	public boolean isCheckChild(String id) throws Exception{
		if(StrKit.isBlank(id))throw new NullPointerException("参数无效");
		return getNewInstance().checkChildExist(id);
	}
	/**
	 * 查询列表
	 * @return list
	 * @throws Exception
	 */
	public List<M> list()throws Exception{
		List<M> list=getNewInstance().queryList();
		return list;
	}
	/**
	 * 查询列表，返回json
	 * @throws Exception
	 */
	public void listJson()throws Exception{
		renderJson(list());
	}
	/**
	 * 查询全部数据，返回JSON
	 * @throws Exception
	 */
	public void queryPageJson()throws Exception{
		queryPageJson(null);
	}
	/**
	 * 根据条件查询，返回JSON数据
	 * @param condition
	 * @throws Exception
	 */
	public void queryPageJson(String condition) throws Exception{
		queryPageJson(null, condition, getSortColumn(), getPageSize(), getRowsSize());
	}
	/**
	 * 分页查询
	 * @param field 要显示的名称
	 * @param condition 条件，可用sqlutils拼接
	 * @param order 排序
	 * @param pageNumber 当前页
	 * @param pageSize 每页数
	 * @return 返回Json数据
	 * @throws Exception
	 */	
	public void queryPageJson(String field,String condition,String order,int pageNumber,int pageSize)throws Exception{
		Page<M> pg=getNewInstance().queryPage(field, condition, order, pageNumber, pageSize);
		Map<String, Object> maps = new HashMap<String, Object>();
		maps.put("total", pg.getTotalRow());
		maps.put("rows", pg.getList());
		this.renderJson(maps);
	}
	/**
	 * 获取当前model实例，用于数据操作使用
	 * @return model
	 */
	public M getNewInstance() throws Exception{
		return modelClass.newInstance();
	}
	/**
	 * 通过req参数获取排序列,没有指定，则以主键排序降序
	 *  sort为排序列名,order为排序方式，默认为desc
	 * @return order by xxx xxx
	 */
	public String getSortColumn(){
		//默认主键降序
		String sort=primaryKey;
		String order="desc";
		if(StrKit.notBlank(getPara("sort")))sort=getPara("sort");
		if(StrKit.notBlank(getPara("order")))order=getPara("order");
		return " order by "+sort+" "+order;
	}	
}
